/*
 * Copyright (c) 2012, personal Inc.
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.
 */

//=============================================================================
/**
 *  @file    stl_iterator_ex.h
 *
 *  This is an internal header file, included by other library headers.
 *
 *  $Id stl_iterator_ex.h 2012-10-04 03:28:24Z shawn chen$
 *
 *  @author chen xiaowei<cxwshawn@yeah.net>.
 */
//=============================================================================
#ifndef STL_ITERATOR_EX_H_INCLUDED
#define STL_ITERATOR_EX_H_INCLUDED


#   ifdef __linux

#   include <bits/stl_iterator_base_types.h>
#   include <bits/cpp_type_traits.h>



// 24.4.2.2.1 filter_back_insert_iterator
  /**
   *  @brief  Turns assignment into insertion.
   *
   *  These are output iterators, constructed from a container-of-T.
   *  Assigning a T to the iterator appends it to the container using
   *  push_back if the condition of the element is true.
   *
   *  Tip:  Using the filter_back_inserter function to create these iterators can
   *  save typing.
  */

  template<typename _Container, typename _UnaryPredicate >
    class filter_back_insert_iterator
    : public std::iterator<std::output_iterator_tag, void, void, void, void>
    {
    protected:
      _Container* container;
        _UnaryPredicate pred;

    public:
      /// A nested typedef for the type of whatever container you used.
      typedef _Container          container_type;
      /// A nested typedef for the type of whatever the unary functor u used.
      typedef _UnaryPredicate     unary_predicate_type;

      /// The only way to create this %iterator is with a container.
      explicit
      filter_back_insert_iterator(_Container& __x) : container(&__x) { }

      /**
       *  @param  value  An instance of whatever type
       *                 container_type::const_reference is; presumably a
       *                 reference-to-const T for container<T>.
       *  @return  This %iterator, for chained operations.
       *
       *  This kind of %iterator doesn't really have a "position" in the
       *  container (you can think of the position as being permanently at
       *  the end, if you like).  Assigning a value to the %iterator will
       *  always append the value to the end of the container.
      */

      filter_back_insert_iterator&
      operator=(typename _Container::const_reference __value)
      {
          /// if the condition is true , push back the node element.
        if( pred(__value) )
        {
            container->push_back(__value);
        }
        return *this;
      }

      /// Simply returns *this.
      filter_back_insert_iterator&
      operator*()
      { return *this; }

      /// Simply returns *this.  (This %iterator does not "move".)
      filter_back_insert_iterator&
      operator++()
      { return *this; }

      /// Simply returns *this.  (This %iterator does not "move".)
      filter_back_insert_iterator
      operator++(int)
      { return *this; }
    };

  /**
   *  @param  x  A container of arbitrary type.
   *  @return  An instance of back_insert_iterator working on @p x.
   *
   *  This wrapper function helps in creating filter_insert_iterator instances.
   *  Typing the name of the %iterator requires knowing the precise full
   *  type of the container, which can be tedious and impedes generic
   *  programming.  Using this function lets you take advantage of automatic
   *  template parameter deduction, making the compiler match the correct
   *  types for you.
  */


  template<typename _Container, typename _UnaryPredicate>
    inline filter_back_insert_iterator<_Container, _UnaryPredicate>
    filter_back_inserter(_Container& __x)
    { return filter_back_insert_iterator<_Container, _UnaryPredicate>(__x); }


#   endif


#endif // STL_ITERATOR_EX_H_INCLUDED
